package spl.manager;

import java.io.*;
import java.net.*;

import spl.utils.GlobalLogger;

/** ThreadedConnectionHandler.
 * is a simple connection handler that creates a thread for every connection
 * @author avikam
 *
 */
public class ThreadedConnectionHandler implements ConnectionHandler {

	/** ConnectionThread.
	 * @author avikam
	 *
	 */
	class ConnectionThread implements Runnable {
		/* Holds the connection to the client */
		private SocketStream clientSocket;
		
		ConnectionThread(SocketStream client) throws UnsupportedEncodingException, IOException {
			this.clientSocket = client;
			
		}
		
		@Override
		public void run() {
			GlobalLogger.getLogger().finest("Comitting session with " + this.clientSocket.s.getInetAddress());
			try {
				
				HTTPResponse requestResult = HTTPRequestHandler.processRequest(this.clientSocket);
				
				GlobalLogger.getLogger().finest("HTTPRequestHandler returned " + requestResult.getResponseCode());
				
				if (requestResult.getMessage() == HTTPResponse.SO_LONG_AND_THANKS_FOR_ALL_THE_FISH)
					WorkManager.stopSock();

			}
			catch (IOException e) {
				GlobalLogger.getLogger().severe("IO Error while processing request");
			} catch (IllegalArgumentException e){
				GlobalLogger.getLogger().severe("Error");
			} finally {
				this.freeResource();
			}
		}
		
		/**
		 * This method close every recourse allocated with the socket
		 * @throws IOException
		 */
		private void freeResource()
		{
			this.clientSocket.freeSocket();
		}
	}
	
	/**
	 * C-tor
	 * Does nothing special
	 */
	public ThreadedConnectionHandler() {
		
	}

	@Override
	/**
	 * Simply create a new thread that would hold the socket;
	 * @param incomingConnection client socket.
	 */
	public void handleConnection(Socket incomingConnection) {
		try {
			//Create a new Runnable object with it's own input/output
			ConnectionThread ct = new ConnectionThread(new SocketStream(incomingConnection));
			// Create the thread
			Thread t = new Thread(ct);
			// Run connection
			t.start();
		} catch (IOException e) {
			// In case of an exception, the thread cannot handle the socket
			// so we close it.
			try {
				GlobalLogger.getLogger().warning("Failed to initialize thread for socket!");
				incomingConnection.close();
			} catch (IOException e1) {
				// Nothing we can do about it.
				GlobalLogger.getLogger().severe("Couldn't close socket!");
			}
		}

	}
}
